#include "log/log.h"
#include "clocker/timer.hpp"
#include "smart/smart_drm.hpp"
#include "../mpp/smart/h264_file_nalu_pars.h"
#include "../mpp/smart/smart_mpp_decoder.hpp"
#include "../rga/smart/smart_rga.hpp"

int main(const int argc, const char* argv[])
{
    uint8_t* demo_src_buf = (uint8_t*)malloc(SmartRga::get_image_size(1920, 1080, RK_FORMAT_YCbCr_420_SP));
    uint8_t* demo_dst_buf = (uint8_t*)malloc(SmartRga::get_image_size(1920, 1080, RK_FORMAT_YUYV_422));
    if (argc != 4) {
        log_error("para failed, simple: ./demo.h264 3840 2160");
        exit(EXIT_FAILURE);
    }
    
    SmartDrm drm;
    SmartRga rga;
    SmartMppDecoder mpp_dec(MPP_VIDEO_CodingAVC);
    H264FileNaluPars h264_nalu;

    drm.init(atoi(argv[2]), atoi(argv[3]), DRM_FORMAT_YUYV);
    h264_nalu.init(argv[1], H264FileNaluPars::FMT_H264);

    while (true) {
        getchar();
        printf("--------------- start ----------------\n");

        std::vector<uint8_t> vec = h264_nalu.get_nalu_frame();
        while (vec.size() < 1000) {
            std::vector<uint8_t> tmp_vec = h264_nalu.get_nalu_frame();
            if (tmp_vec.size() <= 0) {
                log_debug("h264 file read end.");
                exit(EXIT_FAILURE);
            }
            vec.insert(vec.end(), tmp_vec.begin(), tmp_vec.end());
        }

        mpp_dec.sync_decoding(vec.data(), vec.size(), [&drm, &rga, &demo_src_buf, &demo_dst_buf](uint8_t* frm_buf, uint32_t frm_len){
            Timer* timer = Timer::get_instance();
            log_debug("decode callback.");
            if (frm_buf == nullptr || frm_len == 0) {
                log_info("frame read nullptr.");
                return;
            }
            uint64_t ptr_size;
            uint8_t* ptr = drm.get_free_page(&ptr_size);
            SmartRga::cfg_t rga_src_cfg = {
                .width = 1920,
                .height = 1080,
                .format = RK_FORMAT_YCbCr_420_SP,
                .buffer = frm_buf
                // .buffer = demo_src_buf
            };
            SmartRga::cfg_t rga_dst_cfg = {
                .width = 1920,
                .height = 1080,
                .format = RK_FORMAT_YUYV_422,
                // .buffer = ptr
                .buffer = demo_dst_buf
            };
            log_debug("rga src buf: %p, dst buf: %p.", frm_buf, ptr);
            
            int ret = rga.init(rga_src_cfg, rga_dst_cfg);
            if (ret) {
                log_error("rga init failed. ret:%d.", ret);
                return;
            }
            rga.cvtcolor();
            if (ret) {
                log_error("rga cvtcolor failed. ret:%d.", ret);
                return;
            }
            rga.deinit();
            if (ret) {
                log_error("rga init deinit. ret:%d.", ret);
                return;
            }
            log_debug("rga success.");
            if (ptr_size != SmartRga::get_image_size(1920, 1080, RK_FORMAT_YUYV_422)) {
                log_error("ptr_size error.");
                exit(0);
            }
            memcpy(ptr, demo_dst_buf, ptr_size);
            drm.set_page_flip();

            static uint32_t num = 0;
            printf("--------------- end:[%d] timer diff:%ld----------------\n", num++, timer->end());
            timer->begin();
        });
    }

    log_debug("normal exit.");
    drm.deinit();
    return 0;
}